package chess;

import java.lang.Math;

public enum Piece {
	EMPTY (0),
	PAWN_WHITE(1),
	PAWN_BLACK(-1),
	KNIGHT_WHITE(2),
	KNIGHT_BLACK(-2),
	BISHOP_WHITE(3),
	BISHOP_BLACK(-3),
	ROOK_WHITE(4),
	ROOK_BLACK(-4),
	QUEEN_WHITE(5),
	QUEEN_BLACK(-5),
	KING_WHITE(6),
	KING_BLACK(-6),
	ENPASSANT_WHITE(7),  // note: ENPASSANT_WHITE means BLACK can capture
	ENPASSANT_BLACK(-7); //       and vice versa

	private final int _id;

	Piece(int id) {
		_id = id;
	}

	public boolean isEmpty() {
		return (_id == 0);
	}

	public boolean isWhite() {
		return (_id > 0);
	}

	public boolean isBlack() {
		return (_id < 0);
	}

	public boolean isPawn() {
		return (Math.abs(_id) == 1);
	}

	public boolean isBishop() {
		return (Math.abs(_id) == 3);
	}

	public boolean isRook() {
		return (Math.abs(_id) == 4);
	}

	public boolean isQueen() {
		return (Math.abs(_id) == 5);
	}

	public boolean isKing() {
		return (Math.abs(_id) == 6);
	}

	public String toString() {
		switch (_id) {
			case 0: return " ";
			case 1: return "p";
			case 2: return "n";
			case 3: return "b";
			case 4: return "r";
			case 5: return "q";
			case 6: return "k";
			case 7: return "e";
			case -1: return "P";
			case -2: return "N";
			case -3: return "B";
			case -4: return "R";
			case -5: return "Q";
			case -6: return "K";
			case -7: return "E";
			default: return ".";
		}
	}

	//returns true if it is theoretically possible for a piece to move the way specified
	public boolean canMoveGeometric(int file, int rank, int dFile, int dRank, boolean capture) {
		if (_id == 0 || (dFile == 0 && dRank == 0)) {
			return false;
		}

		int pieceType = Math.abs(_id);
		int sign = _id / pieceType;
		int absFile = Math.abs(dFile);
		int absRank = Math.abs(dRank);

		switch (pieceType) {
			case 1:
				if (capture) {
					return (absFile == 1 && dRank == sign);
				} else {
					// Note: be careful because this only works because you can't go out of bounds
					return (dFile == 0 && (dRank == sign || (dRank == 2*sign && (rank == 1 || rank == 6))));
				}
			case 2:
				return (absFile + absRank == 3 && dFile * dRank != 0);
			case 3:
				return (absFile == absRank);
			case 4:
				return (dFile * dRank == 0);
			case 5:
				return ((absFile == absRank) || (dFile * dRank == 0));
			case 6:
				return (absFile <= 1 && absRank <= 1) || (absFile == 2 && absRank == 0);
                                //Fix castling later
			default:
				return false;
		}
	}
}
